const path = require('path');
const cheerio = require('cheerio');
const htmlparser2 = require('htmlparser2');
const DomHandler = require('domhandler');

const pattens = require('./pattens.js');
const domAnalysis = require('./domAnalysis.js');

const TYPEMAP = ['', '单选题', '', '判断题', '编程题'];
const TITLENUM = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
const OPTIONS = ['A', 'B', 'C', 'D', 'E'];
let typeStack = [];

// 解析入口函数
async function parseJson(docxFileQuestion, docxFileAnswer, quesitonsInfo) {
  return new Promise(async (resolve) => {
    writeTitle(
      docxFileQuestion,
      docxFileAnswer,
      quesitonsInfo.previousExamName
    );
    // 遍历所有题目
    for (let i = 0; i < quesitonsInfo.subjectLevelList.length; i++) {
      let currentQuestion = quesitonsInfo.subjectLevelList[i];
      console.log('🎓', `正在解析第${i + 1}题`);
      writeTypeTitle(docxFileQuestion, docxFileAnswer, currentQuestion.type); // 添加题目类型标题
      // 添加题目标题
      await writeQuestionTitle(
        docxFileQuestion,
        currentQuestion.title,
        i,
        currentQuestion.score
      );
      // 添加题目答案
      await writeQuestionAnswer(
        docxFileAnswer,
        currentQuestion.answer,
        currentQuestion.analyzeContent,
        currentQuestion.type,
        i
      );
      // 根据题目类型添加题目内容
      if (currentQuestion.type == 1) {
        // 单选题
        await writeSingleChoiceQuestion(docxFileQuestion, currentQuestion);
      }
    }
    resolve();
  });
}

// 写入标题
function writeTitle(docxFileQuestion, docxFileAnswer, title) {
  let pObjQuestion = docxFileQuestion.createP({
    align: 'center',
  });
  let pObjAnswer = docxFileAnswer.createP({
    align: 'center',
  });
  let config = {
    bold: true,
    font_face: 'Arial',
    font_size: 20,
  };
  pObjQuestion.addText(title, config);
  pObjAnswer.addText(title, config);
}

// 添加题目类型标题
function writeTypeTitle(docxFileQuestion, docxFileAnswer, type) {
  if (!typeStack.includes(type)) {
    let pObjQuestion = docxFileQuestion.createP();
    let pObjAnswer = docxFileAnswer.createP();
    let title = `${TITLENUM[typeStack.length]}、${TYPEMAP[type]}`;
    let config = {
      bold: true,
      font_face: 'Arial',
      font_size: 16,
    };
    pObjQuestion.addText(title, config);
    pObjAnswer.addText(title, config);
    typeStack.push(type);
  }
}

// 添加题目标题
async function writeQuestionTitle(docxFileQuestion, title, ind, score) {
  return new Promise(async (resolve, reject) => {
    let pObj = docxFileQuestion.createP();
    pObj.addText(`${ind + 1}、`);
    const handler = new DomHandler.DomHandler(async (error, dom) => {
      if (error) {
        console.error('AST解析错误：', error);
        reject();
      } else {
        await domAnalysis.domAddDoc(
          dom,
          pObj,
          docxFileQuestion,
          path.join(process.cwd(), path.join('temp', '题目.docx'))
        );
        pObj.addText(`（${score}分）`);
        resolve();
      }
    });
    const parser = new htmlparser2.Parser(handler, { decodeEntities: true });
    title ? parser.write(title) : resolve();
    parser.end();
  });
}

// 添加题目答案
async function writeQuestionAnswer(
  docxFileAnswer,
  answer,
  answerAnalyze,
  type,
  ind
) {
  return new Promise(async (resolve, reject) => {
    let pObj = docxFileAnswer.createP();
    pObj.addText(`${ind + 1}、`);
    const handler = new DomHandler.DomHandler(async (error, dom) => {
      if (error) {
        console.error('AST解析错误：', error);
        reject();
      } else {
        await domAnalysis.domAddDoc(
          dom,
          pObj,
          docxFileAnswer,
          path.join(process.cwd(), path.join('temp', '答案.docx'))
        );
        resolve();
      }
    });
    const parser = new htmlparser2.Parser(handler, { decodeEntities: true });
    answer
      ? parser.write(type === 3 ? (answer == 0 ? '错' : '对') : answer)
      : '';
    answerAnalyze ? parser.write(answerAnalyze) : '';
    parser.end();
    resolve();
  });
}

// 添加单选题内容
async function writeSingleChoiceQuestion(docxFileQuestion, currentQuestion) {
  return new Promise(async (resolve) => {
    let pObj = docxFileQuestion.createP();
    for (let i = 0; i < OPTIONS.length; i++) {
      let currentOption = currentQuestion[`option${OPTIONS[i]}`];
      if (!currentOption) break;
      let titleImgPatten = new RegExp(pattens.imgSrc).exec(currentOption);
      const $ = cheerio.load(currentOption);
      let titleImg =
        titleImgPatten && titleImgPatten[2] ? titleImgPatten[2] : '';
      if (!titleImg && !$('body').text()) break;
      pObj.addText(`${OPTIONS[i]}. `);
      let domhandlerFn = async () => {
        return new Promise((resolve, reject) => {
          const handler = new DomHandler.DomHandler(async (error, dom) => {
            if (error) {
              reject(false);
              console.error('AST解析错误：', error);
            } else {
              await domAnalysis.domAddDoc(
                dom,
                pObj,
                docxFileQuestion,
                path.join(process.cwd(), path.join('temp', '题目.docx'))
              );
              resolve(true);
            }
          });
          const parser = new htmlparser2.Parser(handler, {
            decodeEntities: true,
          });
          currentOption ? parser.write(currentOption) : resolve(true);
          parser.end();
        });
      };
      await domhandlerFn();
      pObj.addText('\n');
    }
    resolve();
  });
}

module.exports = {
  parseJson,
};
